package com.autonavi.yunda.yunji.core.engine.context;

import com.autonavi.yunda.yunji.common.exception.AmapException;
import com.autonavi.yunda.yunji.common.exception.AmapExceptionCode;
import com.autonavi.yunda.yunji.core.enums.EdgeType;
import com.autonavi.yunda.yunji.core.vo.EngineData;
import com.autonavi.yunda.yunji.core.vo.node.BaseNode;
import com.autonavi.yunda.yunji.core.vo.node.EdgeNode;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 节点图
 * @author cizhong.wcs
 * @date 2023/8/23 14:05
 */
public class NodeGraph {
    public String startNode;
    public final Map<String, Node> nameNodeMap = new HashMap<>();

    public NodeGraph(EngineData engineData) {
        List<BaseNode> nodes = engineData.nodes;
        List<EdgeNode> edges = engineData.edges;
        int distinctNodeCount = (int) nodes.stream().map(node -> node.name).distinct().count();
        if (distinctNodeCount != nodes.size()) {
            throw new AmapException(AmapExceptionCode.COMMON_SERVER_WARN, "不允许重复名字节点");
        }
        Set<String> availableNodeNames = edges.stream().flatMap(edge -> Stream.of(edge.head, edge.tail)).collect(Collectors.toSet());
        nodes.stream().filter(n -> availableNodeNames.contains(n.name))
                .forEach(node -> nameNodeMap.put(node.name, new Node(node)));

        edges.forEach(edge -> {
            Node headNode = nameNodeMap.get(edge.head);
            Node tailNode = nameNodeMap.get(edge.tail);
            headNode.addNext(edge.tail);
            tailNode.addPrevious(edge.head);
            if (EdgeType.custom.equals(edge.type)) {
                // 添加连接线函数
                headNode.addSwitcher(edge.tail, edge.getName(), edge.getParams());
            } else if (edge.isDefault) {
                headNode.addDefaultNextNodes(tailNode.getName());
            }
        });
        startNode = nameNodeMap.values()
                .stream()
                .filter(node -> node.getPreviousNodes().isEmpty())
                .findFirst().map(Node::getName)
                .orElseThrow(() -> new AmapException(AmapExceptionCode.COMMON_ILLEGAL_PARAM, "无开始节点"));
    }
}
